#include "Scene/IRenderQueue.h"

#include "Framework/StableHeaders.h"
#include "Geometry/Object.h"
#include "Graphics/IRenderable.h"
#include "Graphics/Technique.h"
#include "Graphics/Material.h"
#include "Scene/IRenderQueueGroup.h"


namespace tyro
{
	namespace Scene
	{


		IRenderQueue::IRenderQueue()
		{
			defaultQueueGroup = RENDER_QUEUE_MAIN;
			defaultRenderablePriority = TYRO_DEFAULT_RENDERING_PRIORITY;
		}

		void IRenderQueue::ProcessVisibleObject( Geometry::Object* obj , Camera::Camera* camera )
		{
			// Notify the active camera with object
			obj->NotifyActiveCamera(camera);

			// If object if visible add to que
			if (obj->IsVisible())
			{
				obj->UpdateRenderQueue(this);
			}
		}

		void IRenderQueue::AddRenderable( Graphics::IRenderable* rend, UINT_8 groupID )
		{
			
			AddRenderable(rend,groupID, defaultRenderablePriority);
		}

		void IRenderQueue::AddRenderable( Graphics::IRenderable* rend, UINT_8 groupID, UINT_16 priority )
		{
			// Find the queue group
			IRenderQueueGroup* queueGroup = GetQueueGroup(groupID);

			Graphics::Technique* tech;

			if (!rend->GetMaterial().IsNull())
			{
				tech = rend->GetMaterial()->GetTechnique(0);
			}

			queueGroup->AddRenderable(rend, tech, priority);
		}

		IRenderQueueGroup* IRenderQueue::GetQueueGroup( UINT_8 groupID )
		{
			// Create group iterator
			// Find priority group
			RenderQueuedGroupMap::iterator i = queuedGroupMap.find(groupID);
			IRenderQueueGroup* renderGroup;

			
			if (i == queuedGroupMap.end())
			{ 
				// If not found create group
				renderGroup = new IRenderQueueGroup();
				// Add to group mapping
				queuedGroupMap.insert(RenderQueuedGroupMap::value_type(groupID, renderGroup));
			}
			else
			{
				renderGroup = i->second;
			}

			return renderGroup;
		}

		IRenderQueue::RenderQueuedGroupMap* IRenderQueue::GetQueuedGroupMap( void )
		{
			return &queuedGroupMap;
		}

	}
}